#include "NetworkList.h"

const double MED_MIN = 0.1;
const double HIGH_MIN = 0.3;

Ecore_List* scan_all(unsigned int& num);

int sort_cb(Network* n1, Network* n2)
{
	return (n1->Quality() < n2->Quality());
}

void double_click_cb(void* data, Evas_Object* obj, void* evt_info)
{
	((NetworkList*) data)->DoubleClick();
}

void rescan_cb(void* data, Evas_Object* obj, void* event_info)
{
	std::cout << "Rescan!" << std::endl;
	((NetworkList*) data)->SetNote(DEFAULT_NOTE);
	ecore_timer_add(0.5, scan_cb, data);
}

void power_off_cb(void* data, Evas_Object* obj, void* event_info)
{
	std::cout << "Power Off!" << std::endl;
	//for testing at least
	elm_exit();
}

NetworkList::NetworkList(Evas_Object* parent, std::string note)
{
	my_nets = NULL;

	parent_win = parent;
	/* add a standard bg */
	bg = elm_bg_add(parent_win);
	evas_object_size_hint_weight_set(bg, 1.0, 1.0);
	elm_win_resize_object_add(parent_win, bg);
	evas_object_show(bg);

	/* add a box object - default is vertical. a box holds children in a row,
	 * either horizontally or vertically. nothing more. */
	box = elm_box_add(parent_win);
	evas_object_size_hint_weight_set(box, 1.0, 1.0);
	elm_win_resize_object_add(parent_win, box);
	evas_object_show(box);
	
	/* now let's add a styled frame for the top - outdent_top style */
	fr0 = elm_frame_add(parent_win);
	elm_frame_style_set(fr0, "outdent_top");
	/* weight here means "dont expand either horizontally OR vertically */
	evas_object_size_hint_weight_set(fr0, 0.0, 0.0);
	/* align here means center horizontally and fill vertically */
	evas_object_size_hint_align_set(fr0, 0.5, -1.0);
	/* add the frame to the end of the box */
	elm_box_pack_end(box, fr0);
	evas_object_show(fr0);

	/* add a padding frame - empty space. medium padding. themes can vary
	 * the amount of padding, as can scaling, so don't depend on your pixel
	 * cound here. add pad frame to styled frame above */
	fr = elm_frame_add(parent_win);
	elm_frame_style_set(fr, "pad_medium");
	elm_frame_content_set(fr0, fr);
	evas_object_show(fr);

	/* add a label widget, set the text and put it in the pad frame */
	lb = elm_label_add(parent_win);
	elm_label_label_set(lb, note.c_str());
	elm_frame_content_set(fr, lb);
	evas_object_show(lb);

	/* add the list widget - it comes in a scroller so pretty easy */
	list = elm_list_add(parent_win);
	/* set the weight to say "expand this entry horizontally AND vertically */
	evas_object_size_hint_weight_set(list, 1.0, 1.0);
	/* set the align to mean "fill the region this widget gets" */
	evas_object_size_hint_align_set(list, -1.0, -1.0);
	elm_box_pack_end(box, list);
	evas_object_show(list);
	evas_object_smart_callback_add(list,"clicked",double_click_cb,(void*)this);
	
	/* add another styled frame - outdent_bottom now */
	fr0 = elm_frame_add(parent_win);
	elm_frame_style_set(fr0, "outdent_bottom");
	/* expand horizontallt but not vertically */
	evas_object_size_hint_weight_set(fr0, 1.0, 0.0);
	/* fill allocated region */
	evas_object_size_hint_align_set(fr0, -1.0, -1.0);
	elm_box_pack_end(box, fr0);
	evas_object_show(fr0);

	/* add medium pad frame inside outdent frame */
	fr = elm_frame_add(parent_win);
	elm_frame_style_set(fr, "pad_medium");
	elm_frame_content_set(fr0, fr);
	evas_object_show(fr);

	/* add horizontal box inside pad frame */
	box2 = elm_box_add(parent_win);
	elm_box_horizontal_set(box2, 1);
	elm_box_homogenous_set(box2, 1);
	elm_frame_content_set(fr, box2);
	evas_object_show(box2);
 
	/* add ok button to box - fill and expand */
	rescan_bt = elm_button_add(parent_win);
	elm_button_label_set(rescan_bt, "Rescan");
	evas_object_size_hint_weight_set(rescan_bt, 1.0, 1.0);
	evas_object_size_hint_align_set(rescan_bt, -1.0, -1.0);
	elm_box_pack_end(box2, rescan_bt);
	evas_object_show(rescan_bt);
	/* and when clicked - run "on_ok" - pass list as data param */
	evas_object_smart_callback_add(rescan_bt, "clicked", rescan_cb, this);
 
	/* add cancel button to box - fill and expand */
	power_off_bt = elm_button_add(parent_win);
	elm_button_label_set(power_off_bt, "Power Down Wi-fi");
	evas_object_size_hint_weight_set(power_off_bt, 1.0, 1.0);
	evas_object_size_hint_align_set(power_off_bt, -1.0, -1.0);
	elm_box_pack_end(box2, power_off_bt);
	evas_object_show(power_off_bt);
	/* and when clicked - run "on_cancel" - pass list as data param */
	evas_object_smart_callback_add(power_off_bt, "clicked", power_off_cb, this);
}

void NetworkList::SetNote(const char* note)
{
	elm_label_label_set(lb, note);
}

int scan_cb(void* list)
{
	((NetworkList*) list)->Scan();
	return ECORE_CALLBACK_CANCEL;
}

void NetworkList::Scan()
{
	unsigned int num = 0;
	show_nets( scan_all(num));
	std::string note;
	std::stringstream out;
	out << "Found " << num;
	if(num == 1)
		out << " network.";
	else
		out << " networks.";
	note = out.str();
	SetNote(note.c_str());
}

void NetworkList::show_nets(Ecore_List* nets)
{
	const Eina_List* list_items;
	elm_list_clear(list);
	if(!nets) return;
	if(my_nets)
	{
		ecore_list_destroy(my_nets);
		my_nets = 0;
	}
		
	ecore_list_sort(nets, ECORE_COMPARE_CB(sort_cb), ECORE_SORT_MAX);
	ecore_list_first_goto(nets);
	
	Evas_Object* icon = 0;
	Network* net;
	while((net = (Network*) ecore_list_current(nets)))
	{

		icon = elm_icon_add(list);
				
		if(net->Quality() >= HIGH_MIN)
		{
			elm_icon_file_set(icon, "/home/root/high_signal.png", 0);
		}
		else if(net->Quality() >= MED_MIN)
		{
			elm_icon_file_set(icon, "/home/root/med_signal.png", NULL);
		}
		else
		{
			elm_icon_file_set(icon, "/home/root/low_signal.png", NULL);
		}
		elm_icon_scale_set(icon, 0, 0);
		elm_icon_smooth_set(icon, true);
		elm_list_item_append(list, net->Name().c_str(), icon, NULL, NULL, net);
		evas_object_show(icon);

		ecore_list_next(nets);
	}
	my_nets = nets;
	elm_list_go(list);
}

Ecore_List* scan_all(unsigned int& num)
{
	std::cout << "Begin scan." << std::endl;
	POpen *po = new POpen("iwlist eth0 scan");
	std::string nl = po->GetData();
	delete po;	
	po = 0;

	size_t pos = 0;
	Ecore_List* li = ecore_list_new();
	Network* nw;
	while((pos = nl.find("Cell", pos)) != std::string::npos)
	{
		nw = new Network(nl.substr(pos));
		ecore_list_append(li, (void*) nw);
		num++;
		pos += 4;
	}
	return li;
}

void NetworkList::DoubleClick()
{
	Elm_List_Item* list_item = elm_list_selected_item_get(list);
	if(list_item)
	{
		Network* sel = (Network*) elm_list_item_data_get(list_item);
		std::cout << "Selected " << sel->Name() << std::endl;
		new ConnectWindow(parent_win, sel);
	}
}
